#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define PRINTERR printf("在%d行,发生错误：0X%X\n \t%s\n", __LINE__, errno, strerror(errno))

typedef struct
{
	int no;
	char name[24];
	char gender;
	char email[256];
	int age;
} Student;

typedef struct
{
	size_t m_StudentNum;
	Student* m_students;
	char m_filePath[255];
} SMSystem;
void clearScreen();
void anyKeyContinue();
void printCgi(const char* f);

SMSystem* createSystem(char* fileName);
void destorySystem(SMSystem* ps);
int saveData(SMSystem* p);
void addStudent(SMSystem* p, Student* s);
void removeStudent(SMSystem* p, char* name);
void printFind(SMSystem* p, char* name);
Student* findStudent(SMSystem* p, const char* name);

void printStudent(Student* p);
void inputStudent(Student* p);

int main(int argn, char** argc)
{
	int opt, exit = 1, close = 1;
	size_t i;
	char fileName[255];
	SMSystem* sys;
	Student* pfinedStu;
	Student tempStu;
	char name[24];
	for (; exit;)
	{
		clearScreen();
		printCgi("system.cfg");
		printf("请选择:");
		scanf("%d", &opt);
		if (opt == 0)
			break;
		else if (opt == 1)
		{
			printf("请输入加载文件名:");
			scanf("%s", fileName);
			sys = createSystem(fileName);
			close = 1;
			if (sys == NULL)
			{
				continue;
			}
			for (; close;)
			{
				printCgi("mainScreen.cfg");
				printf("请输入：");
				scanf("%d", &opt);
				clearScreen();
				switch (opt)
				{
				case 0:
					close = 0;
					break;
				case 1:
					printf("学号\t姓名\t性别\t邮件地址\t年龄\n");
					for (i = 0; i < sys->m_StudentNum; ++i)
					{
						printStudent(sys->m_students + i);
					}
					break;
				case 2:
					printf("请输入学生信息:\n");
					inputStudent(&tempStu);
					addStudent(sys, &tempStu);
					break;
				case 3:
					printf("请输入要删除学生的姓名:");
					scanf("%s", name);
					removeStudent(sys, name);
					break;
				case 4:
					printf("请输入要查找的学生姓名：");
					scanf("%s", name);
					printf("学号\t姓名\t性别\t邮件地址\t年龄\n");
					printFind(sys, name);
					break;
				default:
					printf("请输入有效选项!");
					break;
				}
				anyKeyContinue();
			}
			destorySystem(sys);
			sys = NULL;
		}
		else
		{
			printf("请输入有效数字!\n");
			anyKeyContinue();
		}
	}

	return 0;
}

void clearScreen()
{
	system("cls");
}
void anyKeyContinue()
{
	system("pause");
}

void printCgi(const char* f)
{
	FILE* pcgi;
	char ch;
	pcgi = fopen(f, "r");
	if (pcgi == NULL)
	{
		PRINTERR;
		return;
	}
	clearScreen();
	while ((ch = fgetc(pcgi)) != EOF)
	{
		putchar(ch);
	}
	putchar('\n');
	fclose(pcgi);
}

SMSystem* createSystem(char* fileName)
{
	SMSystem* s;
	size_t readNum;
	FILE* pFile;
	s = (SMSystem*)malloc(sizeof(SMSystem));
	memset(s, 0, sizeof(SMSystem));
	strcpy(s->m_filePath, fileName);
	pFile = fopen(fileName, "ab+");
	if (pFile == NULL)
	{
		free(s);
		PRINTERR;
		fclose(pFile);
		return NULL;
	}
	readNum = fread(&s->m_StudentNum, sizeof(int), 1, pFile);
	if (readNum != 1)
	{
		s->m_StudentNum = 0;
	}
	printf("读取到%d条记录\n", s->m_StudentNum);
	anyKeyContinue();
	if (s->m_StudentNum)
	{
		s->m_students = (Student*)malloc(sizeof(Student) * s->m_StudentNum);
		fread(s->m_students, sizeof(Student), s->m_StudentNum, pFile);
	}
	fclose(pFile);
	return s;
}
void destorySystem(SMSystem* p)
{
	saveData(p);
	free(p->m_students);
	free(p);
}
int saveData(SMSystem* p)
{
	size_t nofwrite;
	int ret = 0;
	FILE* pFile;
	char* path = p->m_filePath;
	pFile = fopen(path, "wb");
	fwrite(&p->m_StudentNum, sizeof(int), 1, pFile);
	nofwrite = fwrite(p->m_students, sizeof(Student), p->m_StudentNum, pFile);
	if (nofwrite != p->m_StudentNum)
	{
		PRINTERR;
		ret = 1;
	}
	fclose(pFile);
	return ret;
}


void printStudent(Student* p)
{
	printf("%d\t%s\t%s\t%s\t%d\n",
		p->no,
		p->name,
		p->gender == 'F' ? "女" : "男",
		p->email,
		p->age
	);
}
void inputStudent(Student* p)
{
	printf("学号:");
	scanf("%d", &p->no);
	printf("姓名:");
	scanf("%s", p->name);
	printf("性别(F\\M):");
	p->gender = getchar();
	getchar();
	printf("邮件地址:");
	scanf("%s", p->email);
	printf("年龄:");
	scanf("%d", &p->age);
}

void addStudent(SMSystem* p, Student* s)
{
	Student* narr;
	p->m_StudentNum++;
	narr = malloc(sizeof(Student) * p->m_StudentNum);
	memcpy(narr, p->m_students, sizeof(Student) *( p->m_StudentNum - 1));
	memcpy(&narr[p->m_StudentNum - 1], s, sizeof(Student));
	free(p->m_students);
	p->m_students = narr;

}
Student* findStudent(SMSystem* p, const char* name)
{
	size_t i;
	for (i = 0; i < p->m_StudentNum; i++)
	{
		if (strcmp(p->m_students[i].name, name) == 0)
		{
			return p->m_students + i;
		}
	}
	return NULL;

}
void removeStudent(SMSystem* p, char* name)
{

	size_t i, j;
	int num;
	Student* newarr;

	for (i = 0, num = 0; i < p->m_StudentNum; i++)
	{
		if (strcmp(p->m_students[i].name, name) == 0)
		{
			num++;
		}
	}

	newarr = malloc((p->m_StudentNum - num) * sizeof(Student));

	for (i = 0, j = 0; i < p->m_StudentNum; i++)
	{
		if (strcmp(p->m_students[i].name, name) != 0)
		{
			memcpy(&newarr[j++], &p->m_students[i], sizeof(Student));
		}
	}
	free(p->m_students);
	p->m_students = newarr;
	p->m_StudentNum = p->m_StudentNum - num;
}

void printFind(SMSystem* p, char* name)
{
	size_t i, n;
	for (i = 0, n = 0; i < p->m_StudentNum; i++)
	{
		if (strcmp(p->m_students[i].name, name) == 0)
		{
			printStudent(&p->m_students[i]);
			n++;
		}
	}
	printf("-----------------------------------\n共找到%d条记录\n", n);
}